"""
核心API模块
统一API响应格式和错误处理
"""
from rest_framework import status
from rest_framework.response import Response
from rest_framework.pagination import PageNumberPagination
from rest_framework.views import exception_handler
from django.http import Http404
from django.core.exceptions import PermissionDenied, ValidationError
import logging

logger = logging.getLogger(__name__)


class StandardResponse:
    """标准API响应格式"""

    @staticmethod
    def success(data=None, message='操作成功', code=status.HTTP_200_OK, extra=None):
        """
        成功响应
        """
        response_data = {
            'success': True,
            'code': code,
            'message': message,
            'data': data,
            'timestamp': timezone.now().isoformat()
        }

        if extra:
            response_data.update(extra)

        return Response(response_data, status=code)

    @staticmethod
    def error(message='操作失败', code=status.HTTP_400_BAD_REQUEST, details=None, extra=None):
        """
        错误响应
        """
        response_data = {
            'success': False,
            'code': code,
            'message': message,
            'timestamp': timezone.now().isoformat()
        }

        if details:
            response_data['details'] = details

        if extra:
            response_data.update(extra)

        return Response(response_data, status=code)


class CustomPagination(PageNumberPagination):
    """自定义分页类"""

    page_size = 20
    page_size_query_param = 'page_size'
    max_page_size = 100

    def get_paginated_response_schema(self, schema):
        """
        获取分页响应schema
        """
        return {
            'type': 'object',
            'properties': {
                'success': {'type': 'boolean'},
                'code': {'type': 'integer'},
                'message': {'type': 'string'},
                'data': {
                    'type': 'object',
                    'properties': {
                        'count': {'type': 'integer'},
                        'next': {'type': 'string'},
                        'previous': {'type': 'string'},
                        'results': schema,
                    }
                },
                'pagination': {
                    'type': 'object',
                    'properties': {
                        'current_page': {'type': 'integer'},
                        'page_size': {'type': 'integer'},
                        'total_pages': {'type': 'integer'},
                        'total_count': {'type': 'integer'},
                    }
                },
                'timestamp': {'type': 'string'}
            }
        }

    def get_paginated_response(self, data):
        """
        自定义分页响应格式
        """
        return Response({
            'success': True,
            'code': status.HTTP_200_OK,
            'message': '获取成功',
            'data': {
                'count': self.page.paginator.count,
                'next': self.get_next_link(),
                'previous': self.get_previous_link(),
                'results': data
            },
            'pagination': {
                'current_page': self.page.number,
                'page_size': self.page_size,
                'total_pages': self.page.paginator.num_pages,
                'total_count': self.page.paginator.count
            },
            'timestamp': timezone.now().isoformat()
        })


class APIViewSetMixin:
    """
    API视图集混入类
    提供通用的API功能
    """

    response_class = StandardResponse
    pagination_class = CustomPagination

    def get_serializer_class(self):
        """
        动态获取序列化器类
        """
        if hasattr(self, 'action_serializer_classes'):
            return self.action_serializer_classes.get(self.action, self.serializer_class)
        return self.serializer_class

    def success_response(self, data=None, message='操作成功', extra=None):
        """
        返回成功响应
        """
        return self.response_class.success(data, message, extra=extra)

    def error_response(self, message='操作失败', details=None, extra=None):
        """
        返回错误响应
        """
        return self.response_class.error(message, details=details, extra=extra)

    def paginate_queryset(self, queryset):
        """
        分页处理查询集
        """
        if hasattr(self, 'pagination_class'):
            page = self.paginate_queryset(queryset)
            if page is not None:
                return page, True
        return queryset, False

    def get_paginated_response(self, data):
        """
        获取分页响应
        """
        if hasattr(self, 'paginator'):
            return self.paginator.get_paginated_response(data)
        return self.success_response(data)


def custom_exception_handler(exc, context):
    """
    自定义异常处理
    """
    response = exception_handler(exc, context)

    if response is None:
        return response

    # 获取异常详细信息
    exception_details = {
        'type': exc.__class__.__name__,
        'message': str(exc),
        'view': str(context['view']),
        'method': context['request'].method,
        'path': context['request'].path
    }

    # 记录异常日志
    logger.error(f"API异常: {exception_details}", exc_info=True)

    # 根据异常类型返回相应的错误响应
    if isinstance(exc, Http404):
        return StandardResponse.error(
            message='资源不存在',
            code=status.HTTP_404_NOT_FOUND,
            details=exception_details
        )

    elif isinstance(exc, PermissionDenied):
        return StandardResponse.error(
            message='权限不足',
            code=status.HTTP_403_FORBIDDEN,
            details=exception_details
        )

    elif isinstance(exc, ValidationError):
        return StandardResponse.error(
            message='数据验证失败',
            code=status.HTTP_400_BAD_REQUEST,
            details={
                'validation_errors': exc.detail,
                **exception_details
            }
        )

    # 默认错误响应
    return StandardResponse.error(
        message='服务器内部错误',
        code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        details=exception_details
    )


class APIVersioningMixin:
    """
    API版本控制混入类
    """

    def determine_version(self, request, *args, **kwargs):
        """
        确定API版本
        """
        # 从URL参数获取版本
        version = request.query_params.get('version')

        # 从Header获取版本
        if not version:
            version = request.META.get('HTTP_API_VERSION')

        # 默认版本
        if not version:
            version = 'v1'

        # 验证版本
        allowed_versions = getattr(self, 'allowed_versions', ['v1', 'v2'])
        if version not in allowed_versions:
            raise ValidationError(f'不支持的API版本: {version}')

        request.version = version
        return version


class CacheMixin:
    """
    缓存混入类
    """

    cache_timeout = 300  # 5分钟
    cache_key_prefix = 'api'

    def get_cache_key(self, *args, **kwargs):
        """
        生成缓存键
        """
        import hashlib

        key_data = f"{self.cache_key_prefix}:{self.__class__.__name__}:{args}:{kwargs}"
        return hashlib.md5(key_data.encode()).hexdigest()

    def get_cached_data(self, cache_key):
        """
        获取缓存数据
        """
        from django.core.cache import cache
        return cache.get(cache_key)

    def set_cached_data(self, cache_key, data):
        """
        设置缓存数据
        """
        from django.core.cache import cache
        cache.set(cache_key, data, self.cache_timeout)

    def invalidate_cache(self, pattern=None):
        """
        清除缓存
        """
        from django.core.cache import cache
        if pattern:
            # 清除匹配模式的所有缓存
            keys = cache.keys(f"{self.cache_key_prefix}:{pattern}*")
            cache.delete_many(keys)
        else:
            # 清除当前类的所有缓存
            keys = cache.keys(f"{self.cache_key_prefix}:{self.__class__.__name__}*")
            cache.delete_many(keys)


class LoggingMixin:
    """
    日志记录混入类
    """

    def log_api_call(self, request, response, execution_time=None):
        """
        记录API调用日志
        """
        from apps.security.models import SecurityAuditLog

        try:
            user = request.user if request.user.is_authenticated else None

            log_data = {
                'user': user,
                'username': user.username if user else request.user,
                'ip_address': self._get_client_ip(request),
                'request_method': request.method,
                'request_path': request.path,
                'http_status': response.status_code,
                'user_agent': request.META.get('HTTP_USER_AGENT', ''),
                'metadata': {
                    'execution_time': execution_time,
                    'response_size': len(response.content) if hasattr(response, 'content') else 0,
                    'view_name': self.__class__.__name__,
                }
            }

            SecurityAuditLog.objects.create(
                event_type=SecurityAuditLog.EventType.DATA_ACCESS,
                event_name=f"API调用: {request.method} {request.path}",
                description=f"{self.__class__.__name__} API接口调用",
                **log_data
            )

        except Exception as e:
            logger.error(f"记录API日志失败: {str(e)}")

    def _get_client_ip(self, request):
        """
        获取客户端IP地址
        """
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip


class ThrottlingMixin:
    """
    限流混入类
    """

    rate_limit = '100/hour'  # 默认限流

    def check_rate_limit(self, request):
        """
        检查请求限流
        """
        from django.core.cache import cache
        from django.http import HttpResponse

        if not hasattr(self, 'rate_limit') or not self.rate_limit:
            return True

        # 解析限流配置
        try:
            limit, period = self.rate_limit.split('/')
            limit = int(limit)
        except ValueError:
            return True

        # 生成限流键
        client_ip = self._get_client_ip(request)
        cache_key = f"rate_limit:{self.__class__.__name__}:{client_ip}"

        # 获取当前计数
        current_count = cache.get(cache_key, 0)

        if current_count >= limit:
            return False

        # 增加计数
        cache.set(cache_key, current_count + 1, self._get_period_seconds(period))
        return True

    def _get_period_seconds(self, period):
        """
        获取周期对应的秒数
        """
        period_map = {
            'second': 1,
            'minute': 60,
            'hour': 3600,
            'day': 86400,
        }
        return period_map.get(period.lower(), 3600)


class BaseAPIView(APIViewSetMixin, APIVersioningMixin, CacheMixin, LoggingMixin, ThrottlingMixin):
    """
    基础API视图类
    集成所有通用功能
    """

    def dispatch(self, request, *args, **kwargs):
        """
        重写dispatch方法，添加通用功能
        """
        import time
        start_time = time.time()

        try:
            # 版本控制
            self.determine_version(request, *args, **kwargs)

            # 限流检查
            if not self.check_rate_limit(request):
                return self.error_response(
                    message='请求过于频繁，请稍后再试',
                    code=status.HTTP_429_TOO_MANY_REQUESTS
                )

            # 执行视图逻辑
            response = super().dispatch(request, *args, **kwargs)

            # 计算执行时间
            execution_time = time.time() - start_time

            # 添加执行时间到响应头
            response['X-Execution-Time'] = str(execution_time)
            response['X-API-Version'] = getattr(request, 'version', 'v1')

            # 记录日志
            self.log_api_call(request, response, execution_time)

            return response

        except Exception as e:
            execution_time = time.time() - start_time

            # 记录异常日志
            self.log_api_call(request, None, execution_time)

            # 返回错误响应
            return self.error_response(
                message=str(e),
                details={
                    'execution_time': execution_time,
                    'type': e.__class__.__name__
                }
            )


# 导入timezone
from django.utils import timezone